package com.example.leavemanagement.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.example.leavemanagement.exception.BusinessException;
import com.example.leavemanagement.exception.ErrorCode;
import com.example.leavemanagement.exception.ThrowUtils;
import com.example.leavemanagement.mapper.ScoreManageMapper;
import com.example.leavemanagement.model.dto.score.AddOrDecreaseScoreRequest;
import com.example.leavemanagement.model.dto.score.QueryScoreRequest;
import com.example.leavemanagement.model.dto.score.UpdateScoreRequest;
import com.example.leavemanagement.model.entity.ScoreManage;
import com.example.leavemanagement.model.entity.User;
import com.example.leavemanagement.model.vo.Analyze.UserScoreAnalyzeVo;
import com.example.leavemanagement.model.vo.ScoreManageVo;

import com.example.leavemanagement.service.ScoreManageService;
import com.example.leavemanagement.service.UserService;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.stream.Collectors;

/**
* @author ASUS
* @description 针对表【score_manage】的数据库操作Service实现
* @createDate 2025-05-24 10:20:57
*/
@Service
public  class ScoreManageServiceImpl extends ServiceImpl<ScoreManageMapper, ScoreManage>
    implements ScoreManageService {

    @Resource
    private TransactionTemplate transactionTemplate;
    @Resource
    private UserService userService;

    @Resource
    @Lazy
    private ScoreManageService scoreManageService;

    @Override
    public long addScore(AddOrDecreaseScoreRequest addOrDecreaseScoreRequest, HttpServletRequest request) {
        ThrowUtils.throwIf(ObjectUtil.isEmpty(addOrDecreaseScoreRequest), ErrorCode.PARAMS_ERROR);
        //判断是否存在用户
        String reason = addOrDecreaseScoreRequest.getReason();

        Long userId = addOrDecreaseScoreRequest.getUserId();
        User user=userService.getById(userId);
        if (ObjectUtil.isEmpty(user)) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR,"该用户不存在");
        }
        String type = addOrDecreaseScoreRequest.getType();
        if (ObjectUtil.isEmpty(type)||(!Objects.equals(type, "加分") && !Objects.equals(type, "减分"))) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "请选择类型(加分还是减分)");
        }
        if(ObjectUtil.isEmpty(reason)){
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "请填写原因");
        }
        if(ObjectUtil.isEmpty(addOrDecreaseScoreRequest.getScore())||addOrDecreaseScoreRequest.getScore()<=0){
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "请填写正确的分数");
        }
        ScoreManage scoreManage = new ScoreManage();
        boolean updateResult= Boolean.TRUE.equals(transactionTemplate.execute(status -> {
            scoreManage.setUserName(user.getUserName());
            scoreManage.setUserId(userId);
            scoreManage.setScore(addOrDecreaseScoreRequest.getScore());
            scoreManage.setReason(addOrDecreaseScoreRequest.getReason());
            scoreManage.setOperatorId(userService.getLoginUser(request).getId());
            scoreManage.setType(type);
            boolean saveScoreResult = this.save(scoreManage);
            if ("加分".equals(type)) {
                user.setScoreSum(user.getScoreSum() + addOrDecreaseScoreRequest.getScore());
            } else if ("减分".equals(type)) {
                user.setScoreSum(user.getScoreSum() - addOrDecreaseScoreRequest.getScore());
            } else {
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "请选择类型(加分还是减分)");
            }
            user.setUpdateTime(new Date());
            user.setEditTime(new Date());
            boolean updateUserResult = userService.updateById(user);
            return saveScoreResult && updateUserResult;
        }));
        if(!updateResult){
            throw new BusinessException(ErrorCode.OPERATION_ERROR,"添加失败");
        }
        return scoreManage.getId();
    }

    @Override
    public boolean updateScore(UpdateScoreRequest updateScoreRequest,HttpServletRequest request) {
        ThrowUtils.throwIf(ObjectUtil.isEmpty(updateScoreRequest), ErrorCode.PARAMS_ERROR);
        //判断是否存在用户
        Long userId = updateScoreRequest.getUserId();
        Long scoreId=updateScoreRequest.getId();

        if (ObjectUtil.isEmpty(scoreManageService.getById(scoreId))) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR,"该记录不存在");
        }
        if (ObjectUtil.isEmpty(userService.getById(userId))) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR,"该用户不存在");
        }
        ScoreManage scoreManage = BeanUtil.copyProperties(updateScoreRequest, ScoreManage.class);
        scoreManage.setOperatorId(userService.getLoginUser(request).getId());
        scoreManage.setUserName(userService.getById(userId).getUserName());
        scoreManage.setUpdateTime(new Date());
        scoreManage.setEditTime(new Date());
        //查看原分数加减
        ScoreManage scoreManageOld = this.getById(scoreId);
        //开启事务
        Boolean updateResult = transactionTemplate.execute(status -> {
            //修改scoreManage表中的分数
            boolean updateScoreResult = this.updateById(scoreManage);
            //修改user表中的总分数
            String type = updateScoreRequest.getType();
            User user = userService.getById(userId);
            if ("加分".equals(type)) {
                if("加分".equals(scoreManageOld.getType())){
                    user.setScoreSum(user.getScoreSum()-scoreManageOld.getScore() + updateScoreRequest.getScore());
                }else if("减分".equals(scoreManageOld.getType())){
                    user.setScoreSum(user.getScoreSum()+scoreManageOld.getScore() + updateScoreRequest.getScore());
                }else {
                    throw new BusinessException(ErrorCode.PARAMS_ERROR, "请选择类型(加分还是减分)");
                }
            } else if ("减分".equals(type)) {
                if("加分".equals(scoreManageOld.getType())){
                    user.setScoreSum(user.getScoreSum()-scoreManageOld.getScore() - updateScoreRequest.getScore());
                }else if("减分".equals(scoreManageOld.getType())){
                    user.setScoreSum(user.getScoreSum()+scoreManageOld.getScore() - updateScoreRequest.getScore());
                }else {
                    throw new BusinessException(ErrorCode.PARAMS_ERROR, "请选择类型(加分还是减分)");
                }
            } else {
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "请选择类型(加分还是减分)");
            }
            user.setUpdateTime(new Date());
            user.setEditTime(new Date());
            boolean updateUserResult = userService.updateById(user);
            return updateScoreResult && updateUserResult;
        });
        if(Boolean.FALSE.equals(updateResult)){
            throw new BusinessException(ErrorCode.OPERATION_ERROR,"更新失败");
        }
        return Boolean.TRUE.equals(updateResult);
    }

    @Override
    public Page<ScoreManageVo> getScoreByPage(QueryScoreRequest queryScoreRequest,HttpServletRequest request) {
        int current = queryScoreRequest.getCurrent();
        int pageSize = queryScoreRequest.getPageSize();
        if(current==0||pageSize==0){
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "请填写正确的页码和页数,不能为0");
        }
        //构造查询条件
        QueryWrapper<ScoreManage> queryWrapper = getQueryWrapper(queryScoreRequest);
        //查询
        Page<ScoreManage> scoreManagePage = this.page(new Page<>(current, pageSize), queryWrapper);
        Page<ScoreManageVo> scoreManageVoPage = new Page<>();
        List<ScoreManage> scorceManageList = scoreManagePage.getRecords();
        List<ScoreManageVo> scoreManageVoList = BeanUtil.copyToList(scorceManageList, ScoreManageVo.class);
        //获取scorceManageList中所有的operatorId
        Set<Long> operatorIdSet = scorceManageList.stream()
                .map(ScoreManage::getOperatorId)
                .collect(Collectors.toSet());

        //根据operatorIdSet查询
        Map<Long, List<User>> operatorMap = userService.listByIds(operatorIdSet).stream()
                .collect(Collectors.groupingBy(User::getId));
        //将查询的User信息转换成UserVo放入scoreManageVoList中
        scoreManageVoList.forEach(scoreManageVo -> {
            Long userId = scoreManageVo.getOperatorId();
            User user=null;
            if (operatorMap.containsKey(userId)) {
                user = operatorMap.get(userId).get(0);
                scoreManageVo.setOperator(userService.getUserVo(user));
            }
        });
        scoreManageVoPage.setRecords(scoreManageVoList);
        return scoreManageVoPage;
    }

    @Override
    public QueryWrapper<ScoreManage> getQueryWrapper(QueryScoreRequest queryScoreRequest) {
        QueryWrapper<ScoreManage> queryWrapper = new QueryWrapper<>();
        if(queryScoreRequest==null){
            return queryWrapper;
        }
        Long userId = queryScoreRequest.getUserId();
        String type = queryScoreRequest.getType();
        Integer score = queryScoreRequest.getScore();
        String sortField = queryScoreRequest.getSortField();
        String sortOrder = queryScoreRequest.getSortOrder();

        queryWrapper.eq(!ObjectUtil.isEmpty(userId), "userId", userId);
        queryWrapper.eq(!ObjectUtil.isEmpty(score), "score", score);
        queryWrapper.eq(!ObjectUtil.isEmpty(type), "type", type);
        queryWrapper.orderBy(StrUtil.isNotEmpty(sortField), sortOrder.equals("ascend"), sortField);
        return queryWrapper;
    }

    @Override
    public boolean deleteScoreById(ScoreManage scoreManage, HttpServletRequest request) {
        Long id = scoreManage.getId();
        Long userId = scoreManage.getUserId();
        String userName = scoreManage.getUserName();
        String type = scoreManage.getType();
        String reason = scoreManage.getReason();
        Date createTime = scoreManage.getCreateTime();
        Date editTime = scoreManage.getEditTime();
        Date updateTime = scoreManage.getUpdateTime();
        Integer score = scoreManage.getScore();
        Integer isDelete = scoreManage.getIsDelete();
        Long operatorId = scoreManage.getOperatorId();
        User user = userService.getById(userId);
        Boolean deleteResult = transactionTemplate.execute(status -> {
            if ("加分".equals(type)) {
                user.setScoreSum(user.getScoreSum() - score);
            } else if ("减分".equals(type)) {
                user.setScoreSum(user.getScoreSum() + score);
            } else {
                throw new BusinessException(ErrorCode.OPERATION_ERROR, "无法删除");
            }
            user.setUpdateTime(new Date());
            boolean updateUserResult = userService.updateById(user);
            boolean deleteScoreResult = this.removeById(id);
            return updateUserResult && deleteScoreResult;
        });
        if (Boolean.FALSE.equals(deleteResult)){
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "删除失败");
        }
        return Boolean.TRUE.equals(deleteResult);
    }

    @Override
    public Page<UserScoreAnalyzeVo> getUserScoreAnalyzeVoByPage(QueryScoreRequest queryScoreRequest, HttpServletRequest request) {
        Long userId = queryScoreRequest.getUserId();
        int current = queryScoreRequest.getCurrent();
        int pageSize = queryScoreRequest.getPageSize();
        QueryWrapper<ScoreManage> queryWrapper = getQueryWrapper(queryScoreRequest);
        Page<ScoreManage> scoreManagePage = this.page(new Page<>(current, pageSize), queryWrapper);
        List<ScoreManage> scorceManageList = scoreManagePage.getRecords();
        if (CollectionUtil.isEmpty(scorceManageList)){
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR,"没有找到相关记录");
        }
        List<UserScoreAnalyzeVo> userScoreAnalyzeVoList = BeanUtil.copyToList(scorceManageList, UserScoreAnalyzeVo.class);

        userScoreAnalyzeVoList.forEach(userScoreAnalyzeVo -> {
            User user = userService.getById(userScoreAnalyzeVo.getUserId());
            userScoreAnalyzeVo.setScoreSum(user.getScoreSum());
            User operators = userService.getById(userScoreAnalyzeVo.getOperatorId());
            userScoreAnalyzeVo.setOperator(userService.getUserVo(operators));
        });
        Page<UserScoreAnalyzeVo> userScoreAnalyzeVoPage=new Page<>(current, pageSize);
        userScoreAnalyzeVoPage.setRecords(userScoreAnalyzeVoList);
        return userScoreAnalyzeVoPage;
    }


}




